package demo.huodongbaoming.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 负载均衡演示控制器
 * 用于展示负载均衡效果，每次请求都会轮询调用不同端口的服务
 */
@RestController
@RequestMapping("/api/demo")
public class LoadBalancerDemoController {

    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    
    @Autowired
    private DiscoveryClient discoveryClient;
    
    @Autowired
    private Environment environment;
    
    @Value("${server.port}")
    private int serverPort;
    
    // 模拟服务实例
    private final List<ServiceInstance> mockInstances = Arrays.asList(
        new DefaultServiceInstance("activity-service-1", "activity-service", "localhost", 8085, false),
        new DefaultServiceInstance("activity-service-2", "activity-service", "localhost", 8086, false)
    );
    
    private final Random random = new Random();
    
    /**
     * 演示负载均衡效果
     * 调用自身服务的实例信息接口，通过负载均衡轮询不同实例
     * @return 当前请求的实例信息
     */
    @GetMapping("/balance")
    public Map<String, Object> demonstrateLoadBalancing() {
        // 使用LoadBalancerClient选择一个服务实例
        ServiceInstance instance = loadBalancerClient.choose("activity-service");
        
        Map<String, Object> result = new HashMap<>();
        result.put("message", "负载均衡演示 - 当前请求来自端口: " + serverPort);
        result.put("currentProfile", getCurrentProfile());
        
        if (instance == null) {
            // 检查可用实例
            List<ServiceInstance> instances = discoveryClient.getInstances("activity-service");
            result.put("error", "无法找到可用的服务实例，请确保服务已在Consul中注册");
            result.put("availableServices", discoveryClient.getServices());
            result.put("availableInstances", instances != null ? instances.size() : 0);
            
            // 尝试查找所有可用服务
            List<String> services = discoveryClient.getServices();
            Map<String, List<ServiceInstance>> allInstances = new HashMap<>();
            for (String service : services) {
                allInstances.put(service, discoveryClient.getInstances(service));
            }
            result.put("allServices", allInstances);
            return result;
        }
        
        // 构建URL并调用
        String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/api/instance/info";
        Map response = restTemplate.getForObject(url, Map.class);
        
        // 获取当前实例的标识
        String instanceTag = "未知";
        Map<String, String> metadata = instance.getMetadata();
        if (metadata != null && metadata.get("management.tags") != null) {
            List<String> tags = List.of(metadata.get("management.tags").split(","));
            for (String tag : tags) {
                if (tag.startsWith("instance-")) {
                    instanceTag = tag;
                    break;
                }
            }
        }
        
        result.put("selectedInstance", "http://" + instance.getHost() + ":" + instance.getPort());
        result.put("instanceTag", instanceTag);
        result.put("instanceInfo", response);
        result.put("timestamp", System.currentTimeMillis());
        
        return result;
    }
    
    /**
     * 连续多次调用，展示负载均衡效果
     * @param count 调用次数
     * @return 多次调用的结果
     */
    @GetMapping("/multiple")
    public Map<String, Object> multipleRequests(Integer count) {
        if (count == null || count <= 0) {
            count = 5; // 默认调用5次
        }
        
        List<Map<String, Object>> responses = new ArrayList<>();
        Map<String, Object> result = new HashMap<>();
        result.put("message", "连续" + count + "次负载均衡调用结果 - 当前请求来自端口: " + serverPort);
        result.put("currentProfile", getCurrentProfile());
        
        // 列出所有可用服务
        List<String> services = discoveryClient.getServices();
        result.put("availableServices", services);
        
        // 检查activity-service是否可用
        List<ServiceInstance> availableInstances = discoveryClient.getInstances("activity-service");
        result.put("activityServiceInstances", availableInstances != null ? availableInstances.size() : 0);
        
        if (availableInstances == null || availableInstances.isEmpty()) {
            result.put("error", "无法找到可用的服务实例，请确保服务已在Consul中注册");
            result.put("responses", responses);
            return result;
        }
        
        try {
            for (int i = 0; i < count; i++) {
                // 使用直接的服务名调用
                String url = "http://activity-service/api/instance/info";
                Map<String, Object> response = restTemplate.getForObject(url, Map.class);
                
                Map<String, Object> callInfo = new HashMap<>();
                callInfo.put("callNumber", i + 1);
                callInfo.put("response", response);
                
                responses.add(callInfo);
            }
        } catch (Exception e) {
            result.put("error", "调用服务时出错: " + e.getMessage());
            result.put("errorType", e.getClass().getName());
            result.put("stackTrace", e.getStackTrace()[0].toString());
        }
        
        result.put("responses", responses);
        
        return result;
    }
    
    /**
     * 获取所有活动服务实例
     * @return 所有活动服务实例
     */
    @GetMapping("/instances")
    public Map<String, Object> getAllInstances() {
        List<ServiceInstance> instances = discoveryClient.getInstances("activity-service");
        
        List<Map<String, Object>> instanceList = new ArrayList<>();
        for (ServiceInstance instance : instances) {
            Map<String, Object> instanceInfo = new HashMap<>();
            instanceInfo.put("host", instance.getHost());
            instanceInfo.put("port", instance.getPort());
            instanceInfo.put("uri", instance.getUri().toString());
            instanceInfo.put("serviceId", instance.getServiceId());
            instanceInfo.put("metadata", instance.getMetadata());
            
            // 获取实例标识
            String instanceTag = "未知";
            Map<String, String> metadata = instance.getMetadata();
            if (metadata != null && metadata.get("management.tags") != null) {
                List<String> tags = List.of(metadata.get("management.tags").split(","));
                for (String tag : tags) {
                    if (tag.startsWith("instance-")) {
                        instanceTag = tag;
                        break;
                    }
                }
            }
            instanceInfo.put("instanceTag", instanceTag);
            
            instanceList.add(instanceInfo);
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("message", "当前活动服务实例列表 - 当前请求来自端口: " + serverPort);
        result.put("currentProfile", getCurrentProfile());
        result.put("count", instances.size());
        result.put("instances", instanceList);
        
        return result;
    }
    
    /**
     * 获取所有活动服务实例（使用负载均衡）
     * @return 所有活动服务实例
     */
    @GetMapping("/instances-lb")
    public Map<String, Object> getAllInstancesWithLoadBalancing() {
        Map<String, Object> result = new HashMap<>();
        result.put("message", "当前活动服务实例列表 - 当前请求来自端口: " + serverPort);
        result.put("currentProfile", getCurrentProfile());
        
        // 列出所有可用服务
        List<String> services = discoveryClient.getServices();
        result.put("availableServices", services);
        
        // 检查activity-service是否可用
        List<ServiceInstance> availableInstances = discoveryClient.getInstances("activity-service");
        result.put("activityServiceInstances", availableInstances != null ? availableInstances.size() : 0);
        if (availableInstances != null && !availableInstances.isEmpty()) {
            List<Map<String, Object>> instanceDetails = new ArrayList<>();
            for (ServiceInstance instance : availableInstances) {
                Map<String, Object> details = new HashMap<>();
                details.put("serviceId", instance.getServiceId());
                details.put("host", instance.getHost());
                details.put("port", instance.getPort());
                details.put("uri", instance.getUri().toString());
                instanceDetails.add(details);
            }
            result.put("instanceDetails", instanceDetails);
        }
        
        try {
            // 直接使用服务名调用，而不是具体的IP和端口
            String url = "http://activity-service/api/demo/instances";
            Map<String, Object> response = restTemplate.getForObject(url, Map.class);
            
            // 添加一些额外信息
            result.put("loadBalanced", true);
            result.put("timestamp", System.currentTimeMillis());
            result.put("response", response);
            
            return result;
        } catch (Exception e) {
            result.put("error", "调用服务时出错: " + e.getMessage());
            result.put("errorType", e.getClass().getName());
            result.put("stackTrace", e.getStackTrace()[0].toString());
            return result;
        }
    }
    
    /**
     * 简单文本接口，直观展示负载均衡效果
     * 每次刷新都会调用不同实例，返回纯文本结果
     * @return 文本结果
     */
    @GetMapping(value = "/text", produces = "text/plain")
    public String balanceText() {
        // 首先尝试使用LoadBalancerClient选择一个服务实例
        ServiceInstance instance = loadBalancerClient.choose("activity-service");
        
        // 如果服务发现失败，则使用备用的随机选择
        if (instance == null) {
            int index = random.nextInt(2);
            instance = mockInstances.get(index);
        }
        
        return "当前请求来自端口: " + serverPort + "\n" +
               "选择的实例: " + instance.getPort();
    }
    
    /**
     * 使用@LoadBalanced RestTemplate直接通过服务名调用
     * 这种方式会自动使用负载均衡，无需手动选择实例
     * @return 负载均衡调用结果
     */
    @GetMapping("/direct")
    public Map<String, Object> directLoadBalancedCall() {
        Map<String, Object> result = new HashMap<>();
        result.put("message", "使用@LoadBalanced RestTemplate直接调用 - 当前请求来自端口: " + serverPort);
        result.put("currentProfile", getCurrentProfile());
        
        // 列出所有可用服务
        List<String> services = discoveryClient.getServices();
        result.put("availableServices", services);
        
        // 检查activity-service是否可用
        List<ServiceInstance> availableInstances = discoveryClient.getInstances("activity-service");
        result.put("activityServiceInstances", availableInstances != null ? availableInstances.size() : 0);
        if (availableInstances != null && !availableInstances.isEmpty()) {
            List<Map<String, Object>> instanceDetails = new ArrayList<>();
            for (ServiceInstance instance : availableInstances) {
                Map<String, Object> details = new HashMap<>();
                details.put("serviceId", instance.getServiceId());
                details.put("host", instance.getHost());
                details.put("port", instance.getPort());
                details.put("uri", instance.getUri().toString());
                instanceDetails.add(details);
            }
            result.put("instanceDetails", instanceDetails);
        }
        
        try {
            // 直接使用服务名调用，而不是具体的IP和端口
            // 格式为 http://服务名/路径
            String url = "http://activity-service/api/instance/info";
            Map response = restTemplate.getForObject(url, Map.class);
            result.put("response", response);
            result.put("timestamp", System.currentTimeMillis());
            return result;
        } catch (Exception e) {
            result.put("error", "调用服务时出错: " + e.getMessage());
            result.put("errorType", e.getClass().getName());
            result.put("stackTrace", e.getStackTrace()[0].toString());
            return result;
        }
    }
    
    /**
     * 使用@LoadBalanced RestTemplate直接通过服务名调用，返回纯文本
     * @return 文本结果
     */
    @GetMapping(value = "/direct/text", produces = "text/plain")
    public String directLoadBalancedText() {
        try {
            // 首先检查服务实例是否存在
            List<ServiceInstance> instances = discoveryClient.getInstances("activity-service");
            if (instances == null || instances.isEmpty()) {
                return "错误：无法找到可用的服务实例，请确保服务已在Consul中注册\n" +
                       "当前请求来自端口: " + serverPort + "\n" +
                       "可用实例数: 0";
            }
            
            // 输出一些调试信息
            StringBuilder debug = new StringBuilder();
            debug.append("可用实例数: ").append(instances.size()).append("\n");
            for (ServiceInstance instance : instances) {
                debug.append("实例: ").append(instance.getServiceId())
                     .append(" - ").append(instance.getHost())
                     .append(":").append(instance.getPort())
                     .append(" (").append(instance.getUri()).append(")\n");
            }
            
            // 直接使用服务名调用，而不是具体的IP和端口
            String url = "http://activity-service/api/instance/text";
            String response = restTemplate.getForObject(url, String.class);
            
            return "当前请求来自端口: " + serverPort + "\n" +
                   "实例响应: " + response + "\n\n" +
                   "调试信息:\n" + debug.toString();
        } catch (Exception e) {
            // 获取可用实例信息用于调试
            List<ServiceInstance> instances = discoveryClient.getInstances("activity-service");
            StringBuilder debug = new StringBuilder();
            debug.append("可用实例数: ").append(instances != null ? instances.size() : 0).append("\n");
            if (instances != null) {
                for (ServiceInstance instance : instances) {
                    debug.append("实例: ").append(instance.getServiceId())
                         .append(" - ").append(instance.getHost())
                         .append(":").append(instance.getPort())
                         .append(" (").append(instance.getUri()).append(")\n");
                }
            }
            
            // 列出所有可用服务
            List<String> services = discoveryClient.getServices();
            debug.append("\n所有可用服务: ").append(services.size()).append("\n");
            for (String service : services) {
                debug.append("服务: ").append(service).append("\n");
                List<ServiceInstance> serviceInstances = discoveryClient.getInstances(service);
                for (ServiceInstance instance : serviceInstances) {
                    debug.append("  - ").append(instance.getHost())
                         .append(":").append(instance.getPort())
                         .append(" (").append(instance.getUri()).append(")\n");
                }
            }
            
            return "当前请求来自端口: " + serverPort + "\n" +
                   "错误信息: " + e.getMessage() + "\n" +
                   "错误类型: " + e.getClass().getName() + "\n\n" +
                   "调试信息:\n" + debug.toString();
        }
    }
    
    /**
     * 获取当前使用的配置文件
     * @return 配置文件名称
     */
    private String getCurrentProfile() {
        String[] activeProfiles = environment.getActiveProfiles();
        if (activeProfiles.length > 0) {
            return String.join(",", activeProfiles);
        } else {
            return "default";
        }
    }
} 